# -*- coding: utf-8 -*-

import os,sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

import re,string,json,shutil
import importlib
from application.settings import BASE_DIR,INSTALLED_APPS


def create(appName):
    models_path = os.path.join(BASE_DIR, appName+'/models.py')

    models = []
    with open(models_path, encoding="utf-8") as f:
        for line in f.readlines():
            cls_match = re.match(r"class\s(.*?)[\(:]", line)
            if cls_match:
                cls_name = cls_match.group(1)
                models.append(cls_name)

    createViews(appName,models)
    createUrls(appName,models)
    createApi(appName,models)
    createIndexCrud(appName,models)

def createViews(appName,models):
    # 读取模板文件内容
    with open(os.path.join(BASE_DIR,"atcode/template_views.txt"), "r", encoding="utf-8") as f:
        template = f.read()

    views_file = os.path.join(BASE_DIR, appName+'/views.py')
    try:
        os.remove(views_file)
        print("views.py文件删除成功")
    except Exception as e:
        print("views.py文件不存在")

    views_path = os.path.join(BASE_DIR, appName+'/views/')
    if not os.path.exists(views_path):
        os.makedirs(views_path)

    package_path = appName.replace('/','.')
    for cls_name in models:
        fPath = os.path.join(views_path,cls_name.lower()+'.py')
        # 定义要替换的字符串
        replacement = {'placeholder': cls_name,'package_path':package_path}
        rewriteTemplate(fPath,template,replacement)

def createUrls(appName,models):
    # 读取模板文件内容
    with open(os.path.join(BASE_DIR,"atcode/template_urls.txt"), "r", encoding="utf-8") as f:
        template = f.read()

    fPath = os.path.join(BASE_DIR, appName+'/urls.py')
    package_path = appName.replace('/','.')
    imports,regiters=('','')
    for cls_name in models:
        imports += string.Template('from ${package_path}.views.${cls_name_lower} import ${cls_name}ViewSet')\
                    .safe_substitute({'package_path':package_path,'cls_name_lower':cls_name.lower(),'cls_name':cls_name})+'\n'
        regiters+= string.Template("system_url.register(r'${cls_name_lower}', ${cls_name}ViewSet)").safe_substitute({'cls_name_lower':cls_name.lower(),'cls_name':cls_name})+'\n'
    
    replacement = {'imports': imports,'regiters':regiters}

    rewriteTemplate(fPath,template,replacement)

def createApi(appName,models):
    # 读取模板文件内容
    with open(os.path.join(BASE_DIR,"atcode/template_api.txt"), "r", encoding="utf-8") as f:
        template = f.read()  

    views_path = os.path.join(BASE_DIR, '../web/src/views/'+appName)
    if not os.path.exists(views_path):
        os.makedirs(views_path)     

    for m in models:
        models_Path = views_path+'/'+m.lower()

        if not os.path.exists(models_Path):
            os.makedirs(models_Path)      

        fPath = os.path.join(models_Path, 'api.js')
        replacement = {'placeholder': appName+'/'+m.lower()}

        rewriteTemplate(fPath,template,replacement)

def createIndexCrud(appName,models):
    # 读取模板文件内容
    with open(os.path.join(BASE_DIR,"atcode/template_index.txt"), "r", encoding="utf-8") as f:
        template_index = f.read()  

    with open(os.path.join(BASE_DIR,"atcode/template_crud.txt"), "r", encoding="utf-8") as f:
        template_crud = f.read() 

    views_path = os.path.join(BASE_DIR, '../web/src/views/'+appName)
    if not os.path.exists(views_path):
        os.makedirs(views_path)     

    # 模块名称为包名 + 类名称
    module_name = appName+".models"

    init_menu = []
    menus ={
        "name": appName,
        "icon": "",
        "sort": 1,
        "is_link": False,
        "is_catalog": True,
        "web_path": "",
        "component": "",
        "component_name": "",
        "status": True,
        "cache": False,
        "visible": True,
        "parent": None,
        "children": [],
        "menu_button": []
        }
    
    # 使用 importlib 模块的 import_module 方法加载模块
    module = importlib.import_module(module_name)    

    for i, m in enumerate(models):
       
        # 获取 m 类
        MyClass = getattr(module, m)

        models_Path = views_path+'/'+m.lower()

        if not os.path.exists(models_Path):
            os.makedirs(models_Path)      

        fPath_index = os.path.join(models_Path, 'index.vue')

        pagename =MyClass._meta.verbose_name[0:-1]+'管理'
        modelname = m.lower()
        replacement_index = {'pagename': pagename,'modelname': modelname}

        rewriteTemplate(fPath_index,template_index,replacement_index)

        fPath_crud = os.path.join(models_Path, 'crud.js')

        replacement_crud = {'placeholder': create_replacement_crud(MyClass)}

        rewriteTemplate(fPath_crud,template_crud,replacement_crud)

        api_pre = r"/api/"+appName+r"/"+m.lower()+r"/"
        api_pre_id = r"/api/"+appName+r"/"+m.lower()+r"/{id}/"
        menu ={
            "name": pagename,
            "icon": "",
            "sort": i+1,
            "is_link": False,
            "is_catalog": False,
            "web_path": "/"+m.lower(),
            "component": appName+"/"+m.lower(),
            "component_name": m.lower(),
            "status": True,
            "cache": False,
            "visible": True,
            "parent": 277,
            "children": [],
            "menu_button": [                    
                    {
                        "name": "查询",
                        "value": "Search",
                        "api": api_pre,
                        "method": 0
                    },
                    {
                        "name": "详情",
                        "value": "Retrieve",
                        "api": api_pre_id,
                        "method": 0
                    },
                    {
                        "name": "新增",
                        "value": "Create",
                        "api": api_pre,
                        "method": 1
                    },
                    {
                        "name": "编辑",
                        "value": "Update",
                        "api": api_pre_id,
                        "method": 2
                    },
                    {
                        "name": "删除",
                        "value": "Delete",
                        "api": api_pre_id,
                        "method": 3
                    }]
            } 
        menus["children"].append(menu)
    init_menu.append(menus)
    f_path = os.path.join(BASE_DIR, appName + '/fixtures/init_menu.json')
    if not os.path.exists(f_path):
        src_folder = os.path.join(BASE_DIR, 'atcode/fixtures')
        dst_folder = os.path.join(BASE_DIR, appName + '/fixtures')
        shutil.copytree(src_folder, dst_folder)

    with open(f_path ,'w',encoding='utf-8') as f:
        json.dump(init_menu, f)

    try:
        exec(
            f"""
from {appName}.fixtures.initialize import Initialize
Initialize(reset={True},app="{appName}").run()
        """
        )
    except ModuleNotFoundError:
        print('模块加载出错')

def create_replacement_crud(model):
    placeholder = ''

    # 读取模板文件内容
    with open(os.path.join(BASE_DIR,"atcode/template_crud_column.txt"), "r", encoding="utf-8") as f:
        template_crud_column= f.read()  

    for field in model._meta.get_fields():
        if field.name != 'id' and hasattr(field, 'verbose_name'):
            replacement = {'title': field.verbose_name,'key':field.name,'type':'input'}
            new_content = string.Template(template_crud_column).safe_substitute(replacement)+'\n'
            placeholder += new_content

    return placeholder

def rewriteTemplate(fPath,template,replacement):
    # 替换模板文件中的占位符
    new_content = string.Template(template).safe_substitute(replacement)

    # 将替换后的内容写入新文件中
    with open(fPath, "w",encoding='utf-8') as f:
        f.write(new_content)

def replaceFileContent(fPath,oldContent,newContent):
    # 打开文件进行读取操作
    with open(fPath, 'r',encoding='utf-8') as f:
        text = f.read()

    # 修改文本内容
    new_text = text.replace(oldContent, newContent)

    # 打开文件进行写入操作（覆盖原内容）
    with open(fPath, 'w',encoding='utf-8') as f:
        f.write(new_text)

if '__name__'=='__name__':
    import django,subprocess 

    # 定义 app 名称
    app_name = "mybus"

    # 1 执行创建应用命令
    cmd = [os.path.join(BASE_DIR,"venv/Scripts/python.exe"), os.path.join(BASE_DIR,"manage.py"), "startapp", app_name]
    subprocess.run(cmd, check=True)

    # 2 新增INSTALLED_APPS 和 urlpatterns
    oldContent = '"dvadmin.system",'
    newContent = oldContent+ f'\n\t"{app_name}",'
    replaceFileContent(os.path.join(BASE_DIR,"application/settings.py"),oldContent,newContent)

    oldContent = 'path("api/system/", include("dvadmin.system.urls")),'
    newContent = oldContent+f'\n\t\t\tpath("api/{app_name}/", include("{app_name}.urls")),'
    replaceFileContent(os.path.join(BASE_DIR,"application/urls.py"),oldContent,newContent)

    # 3 拷贝根据业务创建的models.py文件到应用中
    source_file = os.path.join(BASE_DIR,'atcode/models.py')
    target_folder = os.path.join(BASE_DIR,app_name)

    # 移动文件
    dst_file_path = os.path.join(target_folder, os.path.basename(source_file))
    if os.path.exists(dst_file_path):
        os.remove(dst_file_path)
    os.rename(source_file, dst_file_path)

    # 4 自动化生成代码
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')   
    INSTALLED_APPS.append(app_name)
    django.setup()
    create(app_name)

    # 5 迁移数据库
    cmd = [os.path.join(BASE_DIR,"venv/Scripts/python.exe"), os.path.join(BASE_DIR,"manage.py"), "makemigrations"]
    subprocess.run(cmd, check=True)
    cmd = [os.path.join(BASE_DIR,"venv/Scripts/python.exe"), os.path.join(BASE_DIR,"manage.py"), "migrate"]
    subprocess.run(cmd, check=True)   

    # 6 启动后端。
    cmd = [os.path.join(BASE_DIR,"venv/Scripts/python.exe"), os.path.join(BASE_DIR,"manage.py"), "runserver",'0.0.0.0:8000']
    subprocess.run(cmd, check=True)
